package impl.gui;

import impl.core.UDecideManager;
import impl.events.ChoiceClassExpressionSetEvent;
import impl.gui.listeners.ChoiceListListener;
import impl.gui.listeners.UDecideGUIListener;
import impl.gui.util.ChoiceCellRenderer;
import impl.gui.util.ChoiceTableModel;
import impl.gui.util.UDecideGUIElementFactory;
import impl.parser.ExpressionEditorCustom;
import impl.parser.OWLClassExpressionCheckerCustom;
import impl.reasoning.ChoiceResult;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

import org.protege.editor.core.ui.util.InputVerificationStatusChangedListener;
import org.semanticweb.owlapi.model.OWLClassExpression;

public class ChoicePanel extends JPanel {

	private JPanel										choiceClassExpressionBar;
	private JTable										choiceTable;

	private ExpressionEditorCustom<OWLClassExpression>	choiceClassExpressionEditor;
	private JButton										setChoiceClassExpressionButton;
	private JScrollPane									choiceTableScrollPane;

	public ChoicePanel() {
		buildChoiceClassExpressionBar();
		buildChoiceTable();

		this.setLayout(new BorderLayout());

		this.choiceTableScrollPane = new JScrollPane(this.choiceTable);
		this.choiceTableScrollPane.setBorder(UDecideGUIElementFactory.getBorder("Choice Utilities"));
		this.choiceTableScrollPane.setWheelScrollingEnabled(true);
		// new SmartScroller(this.choiceTableScrollPane);

		this.add(this.choiceClassExpressionBar, BorderLayout.NORTH);
		this.add(this.choiceTableScrollPane, BorderLayout.CENTER);
	}

	public void addUtilityReasoningResults(final Collection<ChoiceResult> results) {
		SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				ChoiceTableModel model = (ChoiceTableModel) ChoicePanel.this.choiceTable.getModel();

				clearChoiceUtilityTable();

				for (ChoiceResult r : results) {
					model.addRow(new Object[] { r.getChoice(), r });
				}

				model.fireTableDataChanged();

				scrollToTop();
			}

		});
	}

	private void scrollToTop() {
		if (((ChoiceTableModel) this.choiceTable.getModel()).getRowCount() > 0) {
			this.choiceTable.setRowSelectionInterval(0, 0);
		}

		this.choiceTableScrollPane.getVerticalScrollBar().setValue(0);
	}

	public void setChoiceCellRenderer(ChoiceCellRenderer choiceCellRenderer) {
		this.choiceTable.setDefaultRenderer(Object.class, choiceCellRenderer);
		this.choiceTable.repaint();
	}

	public void clearChoiceSelection() {
		this.choiceTable.clearSelection();
		this.choiceTable.repaint();
	}

	private void buildChoiceClassExpressionBar() {
		this.setChoiceClassExpressionButton = new JButton("<html>Set Choice Class</html>");
		// this.setChoiceClassExpressionButton = UDecideGUIElementFactory.getButton("Set Choice<br>Class Expression", false, "setChoiceClEx");
		this.setChoiceClassExpressionButton.setEnabled(false);
		this.setChoiceClassExpressionButton.setActionCommand("setChoiceClEx");
		ActionListener setChoiceClassExpressionButtonListener = new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				String clEx = ChoicePanel.this.choiceClassExpressionEditor.getText();
				UDecideGUIListener.getInstance().classExpressionAccepted(new ChoiceClassExpressionSetEvent(clEx));
			}
		};
		this.setChoiceClassExpressionButton.addActionListener(setChoiceClassExpressionButtonListener);

		this.choiceClassExpressionEditor = new ExpressionEditorCustom<OWLClassExpression>(UDecideManager.getInstance().getOWLEditorKit(),
				new OWLClassExpressionCheckerCustom(UDecideManager.getInstance().getOWLEntityChecker(), UDecideManager.getInstance().getOWLlDataFactory()));
		this.choiceClassExpressionEditor.addStatusChangedListener(new InputVerificationStatusChangedListener() {
			@Override
			public void verifiedStatusChanged(boolean newState) {
				ChoicePanel.this.setChoiceClassExpressionButton.setEnabled(newState);
			}
		});

		this.choiceClassExpressionBar = new JPanel();
		// this.choiceClassExpressionBar.setFloatable(false);
		this.choiceClassExpressionBar.setLayout(new GridBagLayout());
		JPanel choiceClExEditorPanel = new JPanel(new BorderLayout());
		choiceClExEditorPanel.add(this.choiceClassExpressionEditor);
		choiceClExEditorPanel.setBorder(UDecideGUIElementFactory.getBorder("Choice Class"));
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.BOTH;
		c.gridx = 0;
		c.gridwidth = 1;
		c.weightx = 7.0 / 8;
		this.choiceClassExpressionBar.add(choiceClExEditorPanel, c);
		c.weightx = 1.0 / 8;
		c.gridx = 1;
		this.choiceClassExpressionBar.add(this.setChoiceClassExpressionButton, c);
	}

	private void buildChoiceTable() {
		ChoiceTableModel choiceTableModel = new ChoiceTableModel();
		this.choiceTable = new JTable(choiceTableModel);
		this.choiceTable.setFillsViewportHeight(true);
		this.choiceTable.setAutoCreateRowSorter(true);
		this.choiceTable.setDefaultRenderer(Object.class, new ChoiceCellRenderer());
		this.choiceTable.getTableHeader().setFont(UDecideGUIElementFactory.getBigFont());
		this.choiceTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		this.choiceTable.getColumnModel().getColumn(0).setPreferredWidth(600);
		this.choiceTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
		this.choiceTable.setRowSorter(new TableRowSorter<TableModel>(this.choiceTable.getModel()));
		// sort by utility descending
		this.choiceTable.getRowSorter().toggleSortOrder(1);
		this.choiceTable.getRowSorter().toggleSortOrder(1);
		// add listeners
		ChoiceListListener l = new ChoiceListListener(this.choiceTable);
		this.choiceTable.getSelectionModel().addListSelectionListener(l);
		this.choiceTable.addMouseListener(l);
	}

	public void repaintChoiceTable() {
		((ChoiceTableModel) this.choiceTable.getModel()).fireTableDataChanged();
		scrollToTop();
	}

	public void clearChoiceUtilityTable() {
		ChoiceTableModel model = (ChoiceTableModel) this.choiceTable.getModel();

		model.getDataVector().removeAllElements();
		model.fireTableDataChanged();
	}
}
